package com.ksyun.alert.utils;

import com.ksyun.alert.biz.bo.timing.TimingExpressionResolveBO;
import com.ksyun.alert.utils.AggregateOperations.AvgOperator;
import com.ksyun.alert.utils.AggregateOperations.RateOperator;
import com.ksyun.alert.utils.AggregateOperations.SumOperator;
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.ksyun.alert.utils.TimeParseUtil.parseTimeToSeconds;

/**
 * QLExpress数学引擎工具类
 * @author: hantou
 * @date: 2024-5-10
 */
@Slf4j
public class QLExpressUtil {

    /**
     * 调用QLExpress计算
     * @param expression 表达式
     * @param paramsMap 参数集
     * @return 计算结果
     */
    public static Object doCalculate(String expression, Map<String, ?> paramsMap) throws Exception {
        ExpressRunner runner = new ExpressRunner();
        runner.addFunction("sum", new SumOperator());
        runner.addFunction("rate", new RateOperator());
        runner.addFunction("avg", new AvgOperator());
        DefaultContext<String, Object> context = new DefaultContext<String, Object>();
        for (Map.Entry<String, ?> entry : paramsMap.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (value instanceof List) {
                context.put(key, value);
            } else if (value instanceof Float){
                context.put(key, value);
            }
        }
        return runner.execute(expression, context, null, true, false);
    }

    /**
     * 进行比较计算
     * @param result 左运算数
     * @param comparison 比较符
     * @param threshold 右运算数
     * @return 比较结果
     */
    public static Boolean doCalComparison(Object result, String comparison, Float threshold) throws Exception {
        ExpressRunner runner = new ExpressRunner();
        runner.addFunction("sum", new SumOperator());
        runner.addFunction("rate", new RateOperator());
        runner.addFunction("avg", new AvgOperator());
        String newComparison = result.toString() + comparison + threshold;
        return (Boolean)runner.execute(newComparison, null, null, true, false);
    }

    /**
     * 解析算式
     * @param expression 算式
     * @param metricList 参数列表
     * @return 表达式解析业务对象
     */
    public static TimingExpressionResolveBO resolveExpression(String expression, List<String> metricList){
        Map<String, Long> metricPeriodMap = new HashMap<>();

        for (String metric : metricList) {
            String regex = metric + "\\[(.*?)\\]";
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(expression);

            while (matcher.find()) {
                String timeString = matcher.group(1);
                Long period = parseTimeToSeconds(timeString);

                metricPeriodMap.put(metric, period);
                expression = expression.replace(matcher.group(), metric);
            }
        }

        return new TimingExpressionResolveBO(expression, metricPeriodMap);
    }
}